﻿/*
*		Êý¾ÝÍ¨ÐÅÐ­Òé´¦Àí,Ö÷ÒªÊý¾Ý´¦Àí²¿·Ö
*/


#include "CxDataHandle.h"
#include <zlib.h>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <opencv2/opencv.hpp>
#include <boost/thread.hpp>



using boost::thread;
using namespace DataRevPart;

const BYTE CxDataHandle_R::REVDATA[]={0x5f,0x6f,0x12};

//Í¨ÐÅÐ­Òé²Û
void	CxDataHandle_R::ConnectedSlot(CxPort *port,size_t no)
{
	BYTE command[3]={0x5f,0x6f,0x00};
	command[2]=no;
	port->WritePort(command,3);
}


//PortÇå¿Õ
void CxDataHandle_R::ClearPort(CxPort *port)
{
	size_t	rdsize=0;
	BYTE	clearbuf[500];
	while(1)
	{	
		rdsize=port->ReadPort(clearbuf,500);
		if(rdsize<500)break;
	}
}

BYTE	*CxDataHandle_R::Uncompress(BYTE *data,ULONG &size)
{
	BYTE *umdata=new BYTE[3*size+50];
	ULONG rtsize=3*size+50;
	int  result=uncompress(umdata,&rtsize,data,size);
	if(result!=0)
	{
		//cout<<"Uncompress is error ..."<<endl;
	}
	else ;//cout<<"Umcompress is complete...."<<endl;
	size=rtsize;
	umdata=(BYTE*)realloc(umdata,size);
	return umdata;
}

Mat    CxDataHandle_R::CombineMat(BYTE * data,ULONG size,int  _row,int _col,short _type)
{
	static int n=0;

	BYTE *undata=Uncompress(data,size);

	Mat mat(_row,_col,CV_8UC3,undata);

	Mat rtmat=mat.clone();

	delete [] undata;

	return rtmat;
}



//Êý¾Ý´¦Àí»Øµ÷º¯Êý
void	CxDataHandle_R::RevFunc(const ERRCODE &e,size_t rtsize,
					CxPort		 *port,
					BYTE		*data,
					ImageHeader imagehead,
					CxLinerBuffer *buffer
					)
{   	
	if(e)
	{
		CX_ERR_MESSAGE(e.message());
	}

	if(rtsize!=imagehead.size)
	{
		//CX_ERR_MESSAGE("Size is not equal....");
		delete [] data;
		ClearPort(port);
	}
	else 
	{
		Mat mat=CombineMat(data,imagehead.size,imagehead._row,imagehead._col,imagehead._type);
		delete [] data;
		buffer->Push(mat);
	}

	port->WritePort(REVDATA,3);

	_cond.notify_one();
}

void		CxDataHandle_R::CombineMat(CxPort *port,CxLinerBuffer *buffer)
{
	if(!port->IsOpen())return ;

	BYTE datahead[16];

	port->ReadPort(datahead,2);

	ImageHeader head;

	if(datahead[0]==0x5f && datahead[1]==0x6f)
	{
		port->ReadPort(&datahead[2],14);
		head._row=(*(int *)&datahead[2]);
		head._col=(*(int *)&datahead[6]);
		head._type=(*(short *)&datahead[10]);
		head.size=(*(ULONG *)&datahead[12]);
		BYTE *imgdata;
		try
		{
			imgdata=new BYTE[head.size];
		}
		catch(std::exception &e)
		{
			CX_ASSERT_MSG(0,e.what());
		}
		Async_Handler handler=boost::bind<void>(&CxDataHandle_R::RevFunc,
									this,_1,_2,port,imgdata,head,buffer);
		port->Async_ReadPort(imgdata,head.size,handler);
	}
	else 
	{
		//cout<<"Datahead is not match...."<<endl;
		ClearPort(port);
		port->WritePort(REVDATA,3);
		return ;
	}

	boost::mutex::scoped_lock lock(_mu);
	//µÈ´ý
	_cond.wait(_mu);
}


//Á¬½ÓÒÔºó·¢ËÍÐÅÏ¢
void CxDataHandle_W::ConnectedSlot(CxPort *port,size_t no)
{
	if(!port->IsOpen())return ;
	BYTE sendbuf[3]={0x5f,0x6f,0x00};
	sendbuf[2]=(BYTE)no;
	port->WritePort(sendbuf,3);
}


//¸Ã·¨²ÉÓÃÍ¬²½»úÖÆ
void CxDataHandle_W::CombineMat(CxPort *port,CxLinerBuffer *buffer)
{	
	
	BYTE datahead[16];
    while(1)
	{
		if(!port->IsOpen())goto __FAILED;

		port->ReadPort(datahead,2);
		
		ImageHeader head;

		if(datahead[0]==0x5f && datahead[1]==0x6f)
		{
			//½âÎöÊý¾ÝÍ·
			port->ReadPort(&datahead[2],14);
			head._row=(*(int *)&datahead[2]);
			head._col=(*(int *)&datahead[6]);
			head._type=(*(short *)&datahead[10]);
			head.size=(*(ULONG *)&datahead[12]);
			BYTE *compressdata;
		
			compressdata=(BYTE*)malloc(head.size);
			//ÅÐ¶ÏÊÇ·ñÓÐ×ã¹»ÄÚ´æ¹©malloc
			if(compressdata==NULL)
			{
				cout<<"Malloc is error...."<<endl;
				return ;
			}
			//¶ÁÈ¡ºóÐøÊý¾Ý
			size_t needsize=head.size;
			size_t rdsize=0;
			size_t currentsize=0;

			//Ñ­»·¶ÁÈ¡Êý¾ÝÖ±ÖÁ¶ÁÈ¡ÍêÊý¾Ý
			while(1)
			{
				rdsize=port->ReadPort(compressdata+currentsize,needsize);
				if(rdsize==needsize)
					break;
				else 
				{
					needsize-=rdsize;
					currentsize+=rdsize;
				}
			}

			//¿ªÊ¼ÐÂÏß³Ì´¦ÀíÊý¾Ý
			//thread(boost::bind<void>(&CxDataHandle_W::CombineMat_thread,this,
			//	buffer,head,compressdata)).detach();

            CombineMat_thread(buffer,head,compressdata);

			goto __SUCCESS;
		}
		else 
			cout<<"Head is not match"<<endl;
	}
__SUCCESS:
	return	;
__FAILED:
	return	;
}

//Uncompress  handle
BYTE *CxDataHandle_W::Uncompress(BYTE *data,ULONG &size)
{
	CX_ASSERT(data);
	CX_ASSERT(size);

	ULONG rtsize=3*size+50;

	BYTE *rtdata=(BYTE *)malloc(rtsize);

	int result=uncompress(rtdata,&rtsize,data,size);

    if(!result);
//		cout<<"Uncompress is complete....."<<endl;
	else 
	{
        //cout<<"Uncompress is error...."<<"The erro  no is "<<result<<endl;
		free(rtdata);
		return NULL;
	}

	size=rtsize;

	return rtdata;
}

//´¦ÀíÏß³Ì
void	CxDataHandle_W::CombineMat_thread(CxLinerBuffer *buffer, ImageHeader head,BYTE *data)
{

	//½øÈëÏß³Ì
	CX_ASSERT(data);
	CX_ASSERT(buffer);

	BYTE *undata=Uncompress(data,head.size);

	if(undata==NULL)
	{
		free(data);
		return ;
	}

	Mat mat=Mat(head._row,head._col,CV_8UC3,undata).clone();
	buffer->Push(mat);
	//ÇåµôÁÙÊ±ÄÚ´æ¿Õ¼ä
	free(undata);
	free(data);
	//·µ»ØÏß³Ì
}
